/*
 * Copyright (c) 2025 CAX Conversion Project
 */
package com.comac.ins.bomt.service.impl;

import com.comac.ins.bomt.common.enums.BizStepEnum;
import com.comac.ins.bomt.common.enums.BomDetailTypeEnum;
import com.comac.ins.bomt.common.enums.BomInfoStatusEnum;
import com.comac.ins.bomt.domain.*;
import com.comac.ins.bomt.domain.vo.*;
import com.comac.ins.bomt.event.*;
import com.comac.ins.bomt.repository.BomRepository;
import com.comac.ins.bomt.service.*;
import com.comac.ins.bomt.utils.BomVersionUtil;
import com.comac.ins.common.core.domain.model.BizEvent;
import com.comac.ins.common.core.domain.model.LoginUser;
import com.comac.ins.common.core.utils.BizAssertUtil;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.json.utils.JsonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author zhanghongyi
 * @date 2024/8/28
 * @description BomGenerateServiceImpl
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class BomGenerateServiceImpl implements BomGenerateService {
    private final BomQueryService bomQueryService;

    private final KeywordListService keywordListService;

    private final BomRepository bomRepository;

    private final BomCoreService bomCoreService;

    private final BomExportService bomExportService;

    /**
     * 开始生成标准装机清单
     */
    @Override
    public List<BomInfoVo> beginGenerateStandard(LoginUser loginUser, Map<String, List<DetailStandardBomVo>> groupedStandardVos, String aircraftModel, String track, BizFileVo fileVo) {
        log.info("begin generate standard bom for track:{}", track);
        List<BomInfo> bomInfoList = bomRepository.initBomRecords(loginUser, groupedStandardVos.keySet().stream().toList(), aircraftModel, track, fileVo);
        //发送标准装机清单生成消息
        for (BomInfo bomInfo : bomInfoList) {
            BizEvent.publishEvent(StandardBomGenerateEvent.builder().detailStandardBomVoList(groupedStandardVos.get(bomInfo.getGroupType())).loginUser(loginUser).bomId(bomInfo.getId()).build());
        }
        return bomInfoList.stream().map(item -> MapstructUtils.convert(item, BomInfoVo.class)).toList();
    }

    @Override
    public void beginGenerateStrength(LoginUser loginUser, String aircraftModel, List<Long> bomIds) {
        List<BomInfo> bomInfos = bomQueryService.getBomInfoByIds(bomIds);
        BizAssertUtil.isTrue(1 == bomInfos.stream().map(BomInfo::getTrack).distinct().toList().size(), "bomIds not belong to single track");
        bomInfos.forEach(bomInfo -> BizAssertUtil.isFalse(StringUtils.equals(bomInfo.getStatus(), BomInfoStatusEnum.DOING.getCode()), "bom is processing,please wait"));
        bomInfos.forEach(bomInfo -> BizAssertUtil.notNull(bomInfo.getStandardBomFileId(), "input is not generate"));
        //获取需删除关键词
        List<String> deleteWords = keywordListService.queryByBindType(loginUser, BizStepEnum.SBOM_QBOM_CONVERT, aircraftModel);
        log.info("begin generate strength bom for track:{},delete keywords:{}", bomInfos.get(0).getTrack(), JsonUtils.toJsonString(deleteWords));
        //更新状态为处理中
        bomInfos.forEach(bomInfo -> {
            bomInfo.setBizStep(BizStepEnum.SBOM_QBOM_CONVERT.getType());
            bomInfo.setStatus(BomInfoStatusEnum.DOING.getCode());
            if (StringUtils.isBlank(bomInfo.getExtraInfo())) {
                bomInfo.setExtraInfo(JsonUtils.toJsonString(BomExtraInfo.builder().deleteWords(deleteWords).build()));
            } else {
                BomExtraInfo bomExtra = JsonUtils.parseObject(bomInfo.getExtraInfo(), BomExtraInfo.class);
                BizAssertUtil.notNull(bomExtra, "parse bom extra fail");
                bomExtra.setDeleteWords(deleteWords);
                bomInfo.setExtraInfo(JsonUtils.toJsonString(bomExtra));
            }
        });
        bomRepository.batchUpdateBom(bomInfos);
        //触发生成事件
        for (BomInfo bomInfo : bomInfos) {
            BizEvent.publishEvent(StrengthBomGenerateEvent.builder().deleteKeywords(deleteWords).bomId(bomInfo.getId()).loginUser(loginUser).build());
        }
    }

    @Override
    public void beginGenerateStrengthVsStandard(LoginUser loginUser, String aircraftModel, String compareTrack, List<Long> bomIds) {
        List<BomInfo> bomInfos = bomQueryService.getBomInfoByIds(bomIds);
        BizAssertUtil.isTrue(1 == bomInfos.stream().map(BomInfo::getTrack).distinct().toList().size(), "bomIds not belong to single track");
        bomInfos.forEach(bomInfo -> BizAssertUtil.isFalse(StringUtils.equals(bomInfo.getStatus(), BomInfoStatusEnum.DOING.getCode()), "bom is processing,please wait"));
        bomInfos.forEach(bomInfo -> BizAssertUtil.notNull(bomInfo.getStandardBomFileId(), "input is not generate"));
        List<BomInfo> bomInfosCompare = bomQueryService.getBomInfoListByModelTrack(aircraftModel, compareTrack);
        bomInfosCompare.forEach(bomInfoCompare -> BizAssertUtil.isFalse(StringUtils.equals(bomInfoCompare.getStatus(), BomInfoStatusEnum.DOING.getCode()), "compare bom is processing,please wait"));
        bomInfos.forEach(bomInfo -> BizAssertUtil.notNull(bomInfo.getStrengthBomFileId(), "input compare is not generate"));
        log.info("begin generate strength vs standard bom for track:{}", bomInfos.get(0).getTrack());
        //更新状态为处理中
        bomRepository.updateBomWithBizStepAndStatus(BizStepEnum.QBOM_SBOM_COMPARE, BomInfoStatusEnum.DOING, bomIds);
        //触发生成事件
        for (BomInfo bomInfo : bomInfos) {
            BizEvent.publishEvent(StrengthStandardCompareEvent.builder().compareTrack(compareTrack).bomId(bomInfo.getId()).loginUser(loginUser).build());
        }
    }

    @Override
    public void beginGenerateStatusVsStrength(LoginUser loginUser, String aircraftModel, List<Long> bomIds) {
        List<BomInfo> bomInfos = bomQueryService.getBomInfoByIds(bomIds);
        BizAssertUtil.isTrue(1 == bomInfos.stream().map(BomInfo::getTrack).distinct().toList().size(), "bomIds not belong to single track");
        bomInfos.forEach(bomInfo -> BizAssertUtil.isFalse(StringUtils.equals(bomInfo.getStatus(), BomInfoStatusEnum.DOING.getCode()), "bom is processing,please wait"));
        bomInfos.forEach(bomInfo -> BizAssertUtil.notNull(bomInfo.getModelStatusBomFileId(), "please upload model status file first"));
        bomInfos.forEach(bomInfo -> BizAssertUtil.notNull(bomInfo.getStrengthVsStandardFileId(), "input is not generate"));
        log.info("begin generate status vs strength bom for track:{}", bomInfos.get(0).getTrack());
        //更新状态为处理中
        bomRepository.updateBomWithBizStepAndStatus(BizStepEnum.MSTS_QBOM_COMPARE, BomInfoStatusEnum.DOING, bomIds);
        //触发生成事件
        for (BomInfo bomInfo : bomInfos) {
            BizEvent.publishEvent(ModelStatusStrengthCompareEvent.builder().bomId(bomInfo.getId()).loginUser(loginUser).build());
        }
    }

    @Override
    public void doStrengthBomGenerate(StrengthBomGenerateEvent event) {
        BomInfo bomInfo = bomQueryService.getBomInfoById(event.getBomId());
        bomInfo.setStatus(BomInfoStatusEnum.FAIL.getCode());
        try {
            //获取标准装机清单明细
            List<DetailStandardBom> standardBomDetails = bomQueryService.queryStandardBomDetailsByBomInfo(bomInfo);
            log.info("doStrengthBomGenerate track:{},groupType:{}.standard size:{}", bomInfo.getTrack(), bomInfo.getGroupType(), standardBomDetails.size());
            //转换为强度数模清单
            List<DetailStrengthBom> strengthBomDetails = bomCoreService.convertStandardToStrength(event.getLoginUser(), standardBomDetails, event.getDeleteKeywords());

            log.info("doStrengthBomGenerate track:{},groupType:{},result size:{}", bomInfo.getTrack(), bomInfo.getGroupType(), strengthBomDetails.size());
            //初始化强度数模清单明细
            bomRepository.initStrengthBomDetail(event.getLoginUser(), bomInfo.getAircraftModel(), bomInfo.getTrack(), bomInfo.getGroupType(), strengthBomDetails);
            //生成摘要
            bomInfo.setStrengthBomSummary(JsonUtils.toJsonString(new SummaryStrengthBomVo(BomVersionUtil.getVersions(strengthBomDetails))));
            //导出并上传文件
            bomInfo.replaceFileId(BomDetailTypeEnum.QBOM, bomExportService.exportStrengthBom(event.getLoginUser(), bomInfo, null));
            bomInfo.setStatus(BomInfoStatusEnum.DONE.getCode());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            bomInfo.setErrorMsg(e.getMessage());
        } finally {
            //查找并修改主记录
            bomRepository.updateBomInfo(bomInfo);
            if (StringUtils.equals(BomInfoStatusEnum.DONE.getCode(), bomInfo.getStatus())) {
                BizEvent.publishEvent(BomFileModifyEvent.builder().loginUser(event.getLoginUser()).bomInfo(bomInfo).build());
            }
        }
        log.info("finish generate strength track:{} groupType:{}", bomInfo.getTrack(), bomInfo.getGroupType());
    }

    @Override
    public void doStandardBomGenerate(StandardBomGenerateEvent event) {
        BomInfo bomInfo = bomQueryService.getBomInfoById(event.getBomId());
        bomInfo.setStatus(BomInfoStatusEnum.FAIL.getCode());
        try {
            log.info("doStandardBomGenerate track:{},group:{},standard size:{}", bomInfo.getTrack(), bomInfo.getGroupType(), event.getDetailStandardBomVoList().size());
            //初始化标准装机清单明细
            bomRepository.initStandardBomDetail(event.getLoginUser(), bomInfo.getAircraftModel(), bomInfo.getTrack(), bomInfo.getGroupType(), event.getDetailStandardBomVoList());
            //生成摘要
            bomInfo.setStandardBomSummary(JsonUtils.toJsonString(new SummaryStandardBomVo(BomVersionUtil.getVersions(event.getDetailStandardBomVoList()))));
            //导出并上传文件
            bomInfo.replaceFileId(BomDetailTypeEnum.SBOM, bomExportService.exportStandardBom(event.getLoginUser(), bomInfo, null));
            bomInfo.setStatus(BomInfoStatusEnum.DONE.getCode());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            bomInfo.setErrorMsg(e.getMessage());
        } finally {
            //更新主记录
            bomRepository.updateBomInfo(bomInfo);
            if (StringUtils.equals(BomInfoStatusEnum.DONE.getCode(), bomInfo.getStatus())) {
                BizEvent.publishEvent(BomFileModifyEvent.builder().loginUser(event.getLoginUser()).bomInfo(bomInfo).build());
            }
        }
        log.info("finish generate standard track:{} groupType:{}", bomInfo.getTrack(), bomInfo.getGroupType());
    }

    @Override
    public void doStatusStrengthCompareGenerate(ModelStatusStrengthCompareEvent event) {
        BomInfo bomInfo = bomQueryService.getBomInfoById(event.getBomId());
        bomInfo.setStatus(BomInfoStatusEnum.FAIL.getCode());
        try {
            List<DetailStrengthStandardChange> strengthChangeDetails = bomQueryService.queryStrengthStandardChangeDetailsByBomInfo(bomInfo);
            List<DetailModelStatus> modelStatusDetails = bomQueryService.queryModelStatusDetailsByBomInfo(bomInfo);
            log.info("doStatusStrengthCompareGenerate track:{},groupType:{}, strength size:{},status size:{}", bomInfo.getTrack(), bomInfo.getGroupType(), strengthChangeDetails.size(), modelStatusDetails.size());
            SummaryStatusStrengthChangeVo compareResult = bomCoreService.compareStatusStrength(event.getLoginUser(), bomInfo, strengthChangeDetails, modelStatusDetails);
            bomRepository.initStatusStrengthChangeDetail(event.getLoginUser(), bomInfo.getAircraftModel(), bomInfo.getTrack(), bomInfo.getGroupType(), compareResult);
            log.info("doStatusStrengthCompareGenerate track:{},groupType:{}, result size:{}", bomInfo.getTrack(), bomInfo.getGroupType(), compareResult.getChangeDetailList().size());
            //生成摘要
            bomInfo.setStatusVsStrengthSummary(JsonUtils.toJsonString(compareResult));
            //导出并上传文件
            bomInfo.replaceFileId(BomDetailTypeEnum.MSTS_QBOM_CHANGE, bomExportService.exportStatusStrengthCompare(event.getLoginUser(), bomInfo, null));
            bomInfo.setStatus(BomInfoStatusEnum.DONE.getCode());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            bomInfo.setErrorMsg(e.getMessage());
        } finally {
            //查找并修改主记录
            bomRepository.updateBomInfo(bomInfo);
            if (StringUtils.equals(BomInfoStatusEnum.DONE.getCode(), bomInfo.getStatus())) {
                BizEvent.publishEvent(BomFileModifyEvent.builder().loginUser(event.getLoginUser()).bomInfo(bomInfo).build());
            }
        }
        log.info("finish generate status vs strength track:{},groupType:{}", bomInfo.getTrack(), bomInfo.getGroupType());
    }

    @Override
    public void doStrengthStandardCompareGenerate(StrengthStandardCompareEvent event) {
        BomInfo bomInfo = bomQueryService.getBomInfoById(event.getBomId());
        bomInfo.setStatus(BomInfoStatusEnum.FAIL.getCode());
        try {
            //对比对象
            BomInfo bomInfoCompare = bomQueryService.getBomInfoByModelTrackAndGroupType(bomInfo.getAircraftModel(), event.getCompareTrack(), bomInfo.getGroupType());
            //获取标准装机清单明细
            List<DetailStandardBom> standardBomDetails = bomQueryService.queryStandardBomDetailsByBomInfo(bomInfo);
            //获取强度数模清单明细
            List<DetailStrengthBom> strengthBomDetails = bomQueryService.queryStrengthBomDetailsByBomInfo(bomInfoCompare);
            log.info("doStrengthStandardCompareGenerate track:{} groupType:{},standard size:{},strength size:{}", bomInfo.getTrack(), bomInfo.getGroupType(), standardBomDetails.size(), strengthBomDetails.size());
            //进行对比
            SummaryStrengthStandardChangeVo compareResult = bomCoreService.compareStrengthStandard(event.getLoginUser(), bomInfo, standardBomDetails, strengthBomDetails);
            log.info("doStrengthStandardCompareGenerate track:{},groupType:{},compare result size:{}", bomInfo.getTrack(), bomInfo.getGroupType(), compareResult.getChangeDetailList().size());
            //初始化强度数模清单与标准装机清单对比明细
            bomRepository.initStrengthStandardChangeDetail(event.getLoginUser(), bomInfo.getAircraftModel(), bomInfo.getTrack(), bomInfo.getGroupType(), compareResult);
            //生成摘要
            bomInfo.setStrengthVsStandardSummary(JsonUtils.toJsonString(compareResult));
            //导出并上传文件
            bomInfo.replaceFileId(BomDetailTypeEnum.QBOM_SBOM_CHANGE, bomExportService.exportStrengthStandardCompare(event.getLoginUser(), bomInfo, null));
            bomInfo.setStatus(BomInfoStatusEnum.DONE.getCode());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            bomInfo.setErrorMsg(e.getMessage());
        } finally {
            //查找并修改主记录
            bomRepository.updateBomInfo(bomInfo);
            if (StringUtils.equals(BomInfoStatusEnum.DONE.getCode(), bomInfo.getStatus())) {
                BizEvent.publishEvent(BomFileModifyEvent.builder().loginUser(event.getLoginUser()).bomInfo(bomInfo).build());
            }
        }
        log.info("finish generate strength vs standard,track:{} groupType:{}", bomInfo.getTrack(), bomInfo.getGroupType());
    }
}
